
#include "member_BCube.h"

using namespace BWE;

member_BCube::member_BCube(BCube* cube)
{
	boss = cube;
	length = 0;
	width = 0;
	height = 0;
	lengthSegments = 1;
	widthSegments = 1;
	heightSegments = 1;
	rebuild();
}
member_BCube::~member_BCube()
{

}

void member_BCube::rebuild()
{
	int columnCount = (lengthSegments + widthSegments) * 2;
	int flankNumVerts = columnCount * (heightSegments + 1);
	int bottomNumVerts = (widthSegments - 1) * (lengthSegments - 1);
	int topNumVerts = bottomNumVerts;
	int totalNumVerts = flankNumVerts + bottomNumVerts + topNumVerts;

	BVectorArray* vertices = boss->vertices();
	BVectorArray* normals = boss->normals();
	if (!vertices || vertices->size() != totalNumVerts)
	{
		vertices = new BVectorArray(totalNumVerts);
		normals = new BVectorArray(totalNumVerts);
		boss->setVertices(vertices);
		boss->setNormals(normals);
	}
	if (!colors || colors->size() != totalNumVerts)
	{
		colors = new BColorArray(totalNumVerts);
		//boss->setColors(colors);
	}
	boss->clearElements();

	BVector min(-length * 0.5f, -width * 0.5f, -height * 0.5f);
	BVector max(length * 0.5f, width * 0.5f, height * 0.5f);

	float dx = length / lengthSegments;
	float dy = width / widthSegments;
	float dz = height / heightSegments;

	{// flank vertex.
		int count = 0;
		for (int i = 0; i < lengthSegments; i++)
		{
			float x = min.x() + dx * i;
			float y = min.y();
			(*colors)[count] = BColor(255, 0, 0);
			(*vertices)[count++] = BVector(x, y, 0);
		}
		for (int i = 0; i < widthSegments; i++)
		{
			float x = max.x();
			float y = min.y() + dy * i;
			(*colors)[count] = BColor(0, 255, 0);
			(*vertices)[count++] = BVector(x, y, 0);
		}
		for (int i = 0; i < lengthSegments; i++)
		{
			float x = max.x() - dx * i;
			float y = max.y();
			(*colors)[count] = BColor(0, 0, 255);
			(*vertices)[count++] = BVector(x, y, 0);
		}
		for (int i = 0; i < widthSegments; i++)
		{
			float x = min.x();
			float y = max.y() - dy * i;
			(*colors)[count] = BColor(255, 255, 0);
			(*vertices)[count++] = BVector(x, y, 0);
		}

		for (int r = 1; r < heightSegments + 1; r++)
		{
			int first = columnCount * r;
			float z = dz * r;
			for (int c = 0; c < columnCount; c++)
			{
				(*colors)[first + c] = (*colors)[c];
				(*vertices)[first + c] = (*vertices)[c] + BVector(0, 0, z);
			}
		}
	}

	{// make flank quads
		BIndexArray* flankIndices = new BIndexArray(columnCount * heightSegments * 4);
		BElement* flankPrimitive = new BElement(Primitive_Quads, flankIndices);
		for (int r = 0; r < heightSegments; r++)
		{
			int head = columnCount * r;
			int pos = columnCount * r * 4;
			for (int c = 0; c < columnCount; c++)
			{
				int index0 = head + c;
				int index1 = head + (c + 1) % columnCount;
				int index2 = index0 + columnCount;
				int index3 = index1 + columnCount;
				(*flankIndices)[pos + c * 4] = index0;
				(*flankIndices)[pos + c * 4 + 1] = index1;
				(*flankIndices)[pos + c * 4 + 2] = index3;
				(*flankIndices)[pos + c * 4 + 3] = index2;
			}
		}
		boss->addElement(flankPrimitive);
	}

	{// make bottom and top vertices.
		int col_count = lengthSegments - 1;
		for (int i = 1; i < lengthSegments; i++)
		{
			float y = dy * i;
			int bottomHead = flankNumVerts + col_count * (i - 1);
			int topHead = bottomHead + bottomNumVerts;
			for (int c = 0; c < col_count; c++)
			{
				const BVector& v = (*vertices)[c + 1];
				(*colors)[bottomHead + c] = BColor(255, 255, 255);
				(*vertices)[bottomHead + c] = v + BVector(0, y, 0);

				(*colors)[topHead + c] = BColor(255, 255, 255);
				(*vertices)[topHead + c] = v + BVector(0, y, height);
			}
		}
	}

	{// make bottom quads.
		int col_count = lengthSegments - 1;
		int row_count = widthSegments - 1;
		BIndexArray* bottomIndices = new BIndexArray(lengthSegments * widthSegments * 4);
		BElement* bottomPrimitive = new BElement(Primitive_Quads, bottomIndices);
		int outerFirst = 0;
		int innerFirst = flankNumVerts;
		int quadCount = 0;
		for (int r = 0; r < row_count - 1; r++)
		{
			int head = flankNumVerts + r * col_count;
			for (int c = 0; c < col_count - 1; c++)
			{
				int index0 = head + c;
				int index1 = index0 + 1;
				int index2 = index0 + col_count;
				int index3 = index1 + col_count;
				(*bottomIndices)[quadCount++] = index0;
				(*bottomIndices)[quadCount++] = index1;
				(*bottomIndices)[quadCount++] = index3;
				(*bottomIndices)[quadCount++] = index2;
			}
		}
		innerIndices.reset();
		for (int i = 0; i < col_count; i++)
			innerIndices.append(innerFirst + i);
		for (int i = 0; i < row_count; i++)
			innerIndices.append(innerFirst + (col_count - 1) + col_count * i);
		for (int i = 0; i < col_count; i++)
			innerIndices.append(innerFirst + (col_count * row_count - 1) - i);
		for (int i = 0; i < row_count; i++)
			innerIndices.append(innerFirst + col_count * (row_count - i - 1));
		if (columnCount > 4)
		{
			int outerIndex = 0;
			int innerPos = 0;
			(*bottomIndices)[quadCount++] = outerIndex;
			(*bottomIndices)[quadCount++] = outerIndex + 1;
			(*bottomIndices)[quadCount++] = innerIndices[innerPos];
			(*bottomIndices)[quadCount++] = outerIndex + columnCount - 1;
			for (int i = 0; i < col_count - 1; i++)
			{
				int index0 = outerIndex + 1 + i;
				int index1 = index0 + 1;
				int index2 = innerPos + i;
				int index3 = index2 + 1;
				(*bottomIndices)[quadCount++] = index0;
				(*bottomIndices)[quadCount++] = index1;
				(*bottomIndices)[quadCount++] = innerIndices[index3];
				(*bottomIndices)[quadCount++] = innerIndices[index2];
			}

			outerIndex += lengthSegments;
			innerPos += col_count;
			(*bottomIndices)[quadCount++] = outerIndex - 1;
			(*bottomIndices)[quadCount++] = outerIndex;
			(*bottomIndices)[quadCount++] = outerIndex + 1;
			(*bottomIndices)[quadCount++] = innerIndices[innerPos];
			for (int i = 0; i < row_count - 1; i++)
			{
				int index0 = outerIndex + 1 + i;
				int index1 = index0 + 1;
				int index2 = innerPos + i;
				int index3 = index2 + 1;
				(*bottomIndices)[quadCount++] = index0;
				(*bottomIndices)[quadCount++] = index1;
				(*bottomIndices)[quadCount++] = innerIndices[index3];
				(*bottomIndices)[quadCount++] = innerIndices[index2];
			}

			outerIndex += widthSegments;
			innerPos += row_count;
			(*bottomIndices)[quadCount++] = outerIndex - 1;
			(*bottomIndices)[quadCount++] = outerIndex;
			(*bottomIndices)[quadCount++] = outerIndex + 1;
			(*bottomIndices)[quadCount++] = innerIndices[innerPos];
			for (int i = 0; i < row_count - 1; i++)
			{
				int index0 = outerIndex + 1 + i;
				int index1 = index0 + 1;
				int index2 = innerPos + i;
				int index3 = index2 + 1;
				(*bottomIndices)[quadCount++] = index0;
				(*bottomIndices)[quadCount++] = index1;
				(*bottomIndices)[quadCount++] = innerIndices[index3];
				(*bottomIndices)[quadCount++] = innerIndices[index2];
			}

			outerIndex += lengthSegments;
			innerPos += col_count;
			(*bottomIndices)[quadCount++] = outerIndex - 1;
			(*bottomIndices)[quadCount++] = outerIndex;
			(*bottomIndices)[quadCount++] = outerIndex + 1;
			(*bottomIndices)[quadCount++] = innerIndices[innerPos];
			for (int i = 0; i < row_count - 1; i++)
			{
				int index0 = outerIndex + 1 + i;
				int index1 = index0 + 1;
				int index2 = innerPos + i;
				int index3 = index2 + 1;
				(*bottomIndices)[quadCount++] = index0;
				(*bottomIndices)[quadCount++] = index1;
				(*bottomIndices)[quadCount++] = innerIndices[index3];
				(*bottomIndices)[quadCount++] = innerIndices[index2];
			}
		}
		boss->addElement(bottomPrimitive);
	}
	{// make top quads.
		int col_count = lengthSegments - 1;
		int row_count = widthSegments - 1;
		BIndexArray* topIndices = new BIndexArray(lengthSegments * widthSegments * 4);
		BElement* topPrimitive = new BElement(Primitive_Quads, topIndices);
		int outerFirst = columnCount * heightSegments;
		int innerFirst = flankNumVerts + bottomNumVerts;
		int quadCount = 0;
		for (int r = 0; r < row_count - 1; r++)
		{
			int head = innerFirst + r * col_count;
			for (int c = 0; c < col_count - 1; c++)
			{
				int index0 = head + c;
				int index1 = index0 + 1;
				int index2 = index0 + col_count;
				int index3 = index1 + col_count;
				(*topIndices)[quadCount++] = index0;
				(*topIndices)[quadCount++] = index1;
				(*topIndices)[quadCount++] = index3;
				(*topIndices)[quadCount++] = index2;
			}
		}
		innerIndices.reset();
		for (int i = 0; i < col_count; i++)
			innerIndices.append(innerFirst + i);
		for (int i = 0; i < row_count; i++)
			innerIndices.append(innerFirst + (col_count - 1) + col_count * i);
		for (int i = 0; i < col_count; i++)
			innerIndices.append(innerFirst + (col_count * row_count - 1) - i);
		for (int i = 0; i < row_count; i++)
			innerIndices.append(innerFirst + col_count * (row_count - i - 1));
		if (columnCount > 4)
		{
			int outerIndex = outerFirst;
			int innerPos = 0;
			(*topIndices)[quadCount++] = outerIndex;
			(*topIndices)[quadCount++] = outerIndex + 1;
			(*topIndices)[quadCount++] = innerIndices[innerPos];
			(*topIndices)[quadCount++] = outerIndex + columnCount - 1;
			for (int i = 0; i < col_count - 1; i++)
			{
				int index0 = outerIndex + 1 + i;
				int index1 = index0 + 1;
				int index2 = innerPos + i;
				int index3 = index2 + 1;
				(*topIndices)[quadCount++] = index0;
				(*topIndices)[quadCount++] = index1;
				(*topIndices)[quadCount++] = innerIndices[index3];
				(*topIndices)[quadCount++] = innerIndices[index2];
			}

			outerIndex += lengthSegments;
			innerPos += col_count;
			(*topIndices)[quadCount++] = outerIndex - 1;
			(*topIndices)[quadCount++] = outerIndex;
			(*topIndices)[quadCount++] = outerIndex + 1;
			(*topIndices)[quadCount++] = innerIndices[innerPos];
			for (int i = 0; i < row_count - 1; i++)
			{
				int index0 = outerIndex + 1 + i;
				int index1 = index0 + 1;
				int index2 = innerPos + i;
				int index3 = index2 + 1;
				(*topIndices)[quadCount++] = index0;
				(*topIndices)[quadCount++] = index1;
				(*topIndices)[quadCount++] = innerIndices[index3];
				(*topIndices)[quadCount++] = innerIndices[index2];
			}

			outerIndex += widthSegments;
			innerPos += row_count;
			(*topIndices)[quadCount++] = outerIndex - 1;
			(*topIndices)[quadCount++] = outerIndex;
			(*topIndices)[quadCount++] = outerIndex + 1;
			(*topIndices)[quadCount++] = innerIndices[innerPos];
			for (int i = 0; i < row_count - 1; i++)
			{
				int index0 = outerIndex + 1 + i;
				int index1 = index0 + 1;
				int index2 = innerPos + i;
				int index3 = index2 + 1;
				(*topIndices)[quadCount++] = index0;
				(*topIndices)[quadCount++] = index1;
				(*topIndices)[quadCount++] = innerIndices[index3];
				(*topIndices)[quadCount++] = innerIndices[index2];
			}

			outerIndex += lengthSegments;
			innerPos += col_count;
			(*topIndices)[quadCount++] = outerIndex - 1;
			(*topIndices)[quadCount++] = outerIndex;
			(*topIndices)[quadCount++] = outerIndex + 1;
			(*topIndices)[quadCount++] = innerIndices[innerPos];
			for (int i = 0; i < row_count - 1; i++)
			{
				int index0 = outerIndex + 1 + i;
				int index1 = index0 + 1;
				int index2 = innerPos + i;
				int index3 = index2 + 1;
				(*topIndices)[quadCount++] = index0;
				(*topIndices)[quadCount++] = index1;
				(*topIndices)[quadCount++] = innerIndices[index3];
				(*topIndices)[quadCount++] = innerIndices[index2];
			}
		}
		boss->addElement(topPrimitive);
	}
	boss->smooth();
}
